/*
 * @Copyright: 2017 www.yyfax.com Inc. All rights reserved.
 */
package com.yyfax.pay.order.controller.web;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.yyfax.commons.lang.BeanUtil;
import com.yyfax.framework.exception.YYException;
import com.yyfax.framework.spring.annotation.JsonParam;
import com.yyfax.framework.yyfax.enums.RspCodeEnum;
import com.yyfax.framework.yyfax.enums.YesNoEnum;
import com.yyfax.pay.common.constants.PayConstants;
import com.yyfax.pay.common.enums.PayOrderRedirectTypeEnum;
import com.yyfax.pay.common.enums.PayRspCodeEnum;
import com.yyfax.pay.common.enums.PayStepEnum;
import com.yyfax.pay.common.enums.PaymentEnum;
import com.yyfax.pay.common.exception.YYPayException;
import com.yyfax.pay.common.exception.YYPayOrderException;
import com.yyfax.pay.config.data.service.MerchantConfigService;
import com.yyfax.pay.config.model.po.MerchantConfigPO;
import com.yyfax.pay.order.data.service.PayOrderService;
import com.yyfax.pay.order.data.service.UserAuthService;
import com.yyfax.pay.order.data.service.UserPaymentService;
import com.yyfax.pay.order.model.po.PayOrderPO;
import com.yyfax.pay.order.model.po.UserPaymentPO;
import com.yyfax.pay.order.model.to.CounterContent;
import com.yyfax.pay.order.model.to.CounterParams;
import com.yyfax.pay.order.model.to.PayOrderParams;
import com.yyfax.pay.order.model.to.WebFormConfirmParams;
import com.yyfax.pay.order.model.to.cardbin.QueryCardBinApiParams;
import com.yyfax.pay.order.model.to.user.UserBankInfoContent;
import com.yyfax.pay.order.model.vo.PayOrderVO;
import com.yyfax.pay.order.model.vo.RouteFormVO;
import com.yyfax.pay.order.service.AuthService;
import com.yyfax.pay.order.service.PayCommonService;
import com.yyfax.pay.order.service.PayService;

/**
 * 支付下单 --> 网关入口
 * 
 * @author buyi
 * @date 2017-04-20 19:53:21
 * @since v1.0.0
 */
@Controller
public class PayWebController {
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private PayService payService;

	@Autowired
	private PayOrderService payOrderService;

	@Autowired
	private MerchantConfigService merchantConfigService;

	@Autowired
	private UserAuthService userAuthService;

	@Autowired
	private UserPaymentService userPaymentService;

	@Autowired
	private PayConstants payConstants; // 支付配置类

	@Autowired
	private AuthService authService;

	@Autowired
	private PayCommonService payCommonService;

	// @RequestMapping({ "", "/", "/index", "/pay/", "/pay/index" })
	// public String index() {
	// return "ordertest";
	// }

	/**
	 * web网关请求支付<br>
	 * 
	 * @author buyi
	 * @throws Throwable
	 * @date 2017-04-11 13:53:47
	 * @since v1.0.0
	 */
	@RequestMapping(method = RequestMethod.POST, path = "/web/pay/gateway")
	public String payGateway(String merchantCode, String sign, @JsonParam("params") PayOrderParams params, Model model) throws Throwable {
		logger.debug("enter pay order ……");

		if (StringUtils.isBlank(merchantCode) || StringUtils.isBlank(sign) || params == null) {
			throw new YYPayException(RspCodeEnum.COMMON_ERROR_PARAMETER_INVALID, "参数merchantCode/sign/params不能为空");
		}

		// 1.校验参数
		params.validate();

		// 2.验签
		MerchantConfigPO merchantConfigPO = merchantConfigService.queryByMerchantCode(params.getMerchantCode());
		if (merchantConfigPO == null || !YesNoEnum.YES.isValue(merchantConfigPO.getState())) {
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_MERCHANT_NOT_EXISTS, "不存在[" + params.getMerchantCode() + "]商户信息，或者状态无效", "无效请求");
		}

		String targetSign = params.sign(merchantConfigPO.getSignKey());
		if (!StringUtils.equals(targetSign, sign)) {
			throw new YYPayException(RspCodeEnum.COMMON_ERROR_NO_SIGN_AUTHENTICATION,
					"签名失败,srcSign:" + sign + ",target:" + targetSign + ",请求参数：" + params, "无效请求");
		}

		// 校验身份证号
		userAuthService.checkIdNoAndName(params.getMerchantCode(), params.getUserId(), params.getIdNo(), params.getName());

		// 持久化支付订单信息
		PayOrderVO payOrderVO = payService.savePayOrder(params);

		// 重定向路径
		String path = "";
		RouteFormVO<?> routeFormVO = payService.payRoutePage(payOrderVO, params.getIdNo(), params.getName(), params.getCardNo());
		if (PayOrderRedirectTypeEnum.REAL_NAME.isValue(routeFormVO.getRedirectType())) { // 如果是实名认证页面
			path = "/web/pay/real_name";
		} else if (PayOrderRedirectTypeEnum.SELECT.isValue(routeFormVO.getRedirectType())) { // 如果是支付模式选择页面
			path = "/web/pay/select_mode";
		} else if (PayOrderRedirectTypeEnum.COUNTER.isValue(routeFormVO.getRedirectType())) {// 如果是跳转到收银台类型
			path = "/web/pay/counter";
		} else {
			throw new YYException(PayRspCodeEnum.COMMON_ERROR_BAD_REQUEST, "支付网关模式，非法的跳转类型");
		}

		model.addAttribute("redirectUrl", path);
		model.addAttribute("form", BeanUtil.toNonEmptyMap(routeFormVO.getParams()));

		return "guide";
	}

	/**
	 * 跳转到三要素填写页面
	 * 
	 * @author buyi
	 * @date 2017-04-17 17:56:44
	 * @since v1.0.0
	 * @param mav
	 * @return
	 * @throws YYException
	 */
	@RequestMapping({ "/web/pay/real_name" })
	public ModelAndView realNameForm(WebFormConfirmParams authFormParams) throws YYPayException, YYException {
		authFormParams.checkSign(payConstants.getSignKey());

		try {
			ModelAndView mav = new ModelAndView();
			mav.addAllObjects(BeanUtil.toNonEmptyMap(authFormParams));

			// 三要素页面带查询卡bin接口，增加权限控制，对商户号和订单号签名
			QueryCardBinApiParams cardBinParams = new QueryCardBinApiParams(authFormParams.getMerchantCode(), authFormParams.getPayOrderId());
			mav.addObject("cardBinSign", cardBinParams.sign(payConstants.getSignKey()));

			mav.setViewName("realname");
			return mav;
		} catch (Exception e) {
			throw new YYPayOrderException(authFormParams.getPayOrderId(), authFormParams.getMerchantCode(), e);
		}
	}

	/**
	 * 跳转到支付模式选择页面
	 * 
	 * @author buyi
	 * @date 2017-04-17 17:56:44
	 * @since v1.0.0
	 * @param mav
	 * @return
	 * @throws Exception
	 */
	@RequestMapping({ "/web/pay/select_mode" })
	public ModelAndView selectMode(WebFormConfirmParams authFormParams) throws Exception {
		authFormParams.checkSign(payConstants.getSignKey());

		try {
			ModelAndView mav = new ModelAndView();
			mav.addAllObjects(BeanUtil.toNonEmptyMap(authFormParams));

			// 填充默认用户默认默认信息，用于页面展示
			PayOrderPO payOrderPO = payOrderService.queryByPayOrderId(authFormParams.getMerchantCode(), authFormParams.getPayOrderId());
			if (payOrderPO == null) {
				throw new YYException(PayRspCodeEnum.COMMON_ERROR_OBJECT_NOT_FOUND, "订单不存在", "无效订单");
			}

			UserBankInfoContent content = authService.queryDefaultUserPayment(authFormParams.getMerchantCode(), payOrderPO.getUserId());
			mav.addAllObjects(BeanUtil.toNonEmptyMap(content));

			mav.setViewName("select");
			return mav;
		} catch (Exception e) {
			throw new YYPayOrderException(authFormParams.getPayOrderId(), authFormParams.getMerchantCode(), e);
		}
	}

	/**
	 * 跳转到收银台
	 * 
	 * @author buyi
	 * @date 2017-04-14 08:32:31
	 * @since v1.0.0
	 * @return
	 * @throws Exception
	 */
	@RequestMapping({ "/web/pay/counter" })
	public ModelAndView counter(CounterParams params) throws Exception {
		// 1.校验params数据完整性
		params.validate();
		// 2.校验签名
		params.checkSign(payConstants.getSignKey());

		// 判断用户是否首次投资，且为快钱支付，则收银台不显示手机号码
		boolean isPhone = true; // true表示要输如手机号码，false表示不需要
		PayOrderVO payOrderVO = payOrderService.queryPayOrderVO(params.getPayOrderId(), params.getMerchantCode());
		if (payOrderVO == null || payOrderVO.getPayOrderExtPO() == null) {
			throw new YYException(PayRspCodeEnum.COMMON_ERROR_OBJECT_NOT_FOUND, "订单不存在", "无效订单");
		}

		try {

			// 判断订单已经支付，则跳出
			if (payOrderVO.getStepSuccess(PayStepEnum.STEP2_SUBMIT_ORDER) != null || payOrderVO.getStepLast(PayStepEnum.STEP4_PAY_RESULT) != null) {
				throw new YYPayException(PayRspCodeEnum.PAY_CODE_PAY_ORDER_PAID, "订单号：" + payOrderVO.getPayOrderId() + "已经支付，或者已经产生异步回调");
			}

			UserPaymentPO userPaymentPO = userPaymentService.query(params.getMerchantCode(), payOrderVO.getUserId(), params.getPaymentCode());
			if (userPaymentPO != null && YesNoEnum.YES.isValue(userPaymentPO.getState())) {
				// 如果存在鉴权信息，且鉴权信息有效，

				if (PaymentEnum.QUICK_PAY.isValue(params.getPaymentCode())
						|| (PaymentEnum.FUIOU.isValue(params.getPaymentCode()) && StringUtils.isNotBlank(userPaymentPO.getPhone()))) {
					// 如果是快钱,或者富友且手机号不为空，则不需要展示手机号码
					isPhone = false;
				}

			}

			CounterContent counterInfo = payService.getCounteInfo(payOrderVO);
			counterInfo.setSign(params.getSign());

			ModelAndView mav = new ModelAndView();
			mav.addAllObjects(BeanUtil.toNonEmptyMap(counterInfo));
			mav.addObject("isPhone", isPhone);
			mav.addObject("formToken", payCommonService.generateDuplicateToken(params.getPayOrderId()));
			mav.setViewName("counter");
			return mav;
		} catch (Exception e) {
			throw new YYPayOrderException(params.getPayOrderId(), params.getMerchantCode(), e);
		}
	}
}
